package com.example.service.impl;

import com.example.common.Result;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import com.example.service.PhoneVerificationService;
import com.example.service.SmsService;
import com.example.service.SystemConfigService;
import com.example.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 手机号验证服务实现类
 */
@Slf4j
@Service
public class PhoneVerificationServiceImpl implements PhoneVerificationService {
    
    @Autowired
    private SmsService smsService;
    
    @Autowired
    private SystemConfigService systemConfigService;
    
    @Autowired
    private RedisUtil redisUtil;
    
    @Autowired
    private UserMapper userMapper;
    
    private static final String REGISTER_CODE_PREFIX = "phone:register:code:";
    private static final String LOGIN_CODE_PREFIX = "phone:login:code:";
    private static final String SEND_LIMIT_PREFIX = "phone:send:limit:";
    
    @Override
    public Result<Void> sendRegisterCode(String phone) {
        // 检查手机号注册功能是否启用
        if (!systemConfigService.isPhoneRegisterEnabled()) {
            return Result.error("手机号注册功能未启用");
        }
        
        // 验证手机号格式
        if (!smsService.isValidPhone(phone)) {
            return Result.error("手机号格式不正确");
        }
        
        // 检查手机号是否已注册
        if (isPhoneRegistered(phone)) {
            return Result.error("该手机号已注册");
        }
        
        // 检查发送频率限制
        if (isRateLimited(phone, "register")) {
            return Result.error("发送过于频繁，请稍后再试");
        }
        
        // 生成验证码
        String code = smsService.generateVerificationCode();
        
        // 发送短信
        boolean sent = smsService.sendVerificationCode(phone, code, "register");
        if (!sent) {
            return Result.error("验证码发送失败，请稍后重试");
        }
        
        // 保存验证码到Redis
        int expireTime = systemConfigService.getIntConfig("phone.code.expire", 300);
        redisUtil.set(REGISTER_CODE_PREFIX + phone, code, expireTime);
        
        // 设置发送频率限制（60秒内不能重复发送）
        redisUtil.set(SEND_LIMIT_PREFIX + phone + ":register", "1", 60);
        
        log.info("注册验证码发送成功: phone={}", phone);
        return Result.success();
    }
    
    @Override
    public Result<Void> sendLoginCode(String phone) {
        // 检查手机号登录功能是否启用
        if (!systemConfigService.isPhoneLoginEnabled()) {
            return Result.error("手机号登录功能未启用");
        }
        
        // 验证手机号格式
        if (!smsService.isValidPhone(phone)) {
            return Result.error("手机号格式不正确");
        }
        
        // 检查手机号是否已注册
        if (!isPhoneRegistered(phone)) {
            return Result.error("该手机号未注册");
        }
        
        // 检查发送频率限制
        if (isRateLimited(phone, "login")) {
            return Result.error("发送过于频繁，请稍后再试");
        }
        
        // 生成验证码
        String code = smsService.generateVerificationCode();
        
        // 发送短信
        boolean sent = smsService.sendVerificationCode(phone, code, "login");
        if (!sent) {
            return Result.error("验证码发送失败，请稍后重试");
        }
        
        // 保存验证码到Redis
        int expireTime = systemConfigService.getIntConfig("phone.code.expire", 300);
        redisUtil.set(LOGIN_CODE_PREFIX + phone, code, expireTime);
        
        // 设置发送频率限制（60秒内不能重复发送）
        redisUtil.set(SEND_LIMIT_PREFIX + phone + ":login", "1", 60);
        
        log.info("登录验证码发送成功: phone={}", phone);
        return Result.success();
    }
    
    @Override
    public Result<Void> verifyRegisterCode(String phone, String code) {
        if (!systemConfigService.isPhoneRegisterEnabled()) {
            return Result.error("手机号注册功能未启用");
        }
        
        String savedCode = (String) redisUtil.get(REGISTER_CODE_PREFIX + phone);
        if (savedCode == null) {
            return Result.error("验证码已过期或不存在");
        }
        
        if (!savedCode.equals(code)) {
            return Result.error("验证码错误");
        }
        
        // 验证成功后清除验证码
        clearVerificationCode(phone, "register");
        
        log.info("注册验证码验证成功: phone={}", phone);
        return Result.success();
    }
    
    @Override
    public Result<Void> verifyLoginCode(String phone, String code) {
        if (!systemConfigService.isPhoneLoginEnabled()) {
            return Result.error("手机号登录功能未启用");
        }
        
        String savedCode = (String) redisUtil.get(LOGIN_CODE_PREFIX + phone);
        if (savedCode == null) {
            return Result.error("验证码已过期或不存在");
        }
        
        if (!savedCode.equals(code)) {
            return Result.error("验证码错误");
        }
        
        // 验证成功后清除验证码
        clearVerificationCode(phone, "login");
        
        log.info("登录验证码验证成功: phone={}", phone);
        return Result.success();
    }
    
    @Override
    public boolean isPhoneRegistered(String phone) {
        try {
            User user = userMapper.selectByPhone(phone);
            return user != null;
        } catch (Exception e) {
            log.error("检查手机号是否注册失败: phone={}", phone, e);
            return false;
        }
    }
    
    @Override
    public void clearVerificationCode(String phone, String type) {
        try {
            String prefix = "register".equals(type) ? REGISTER_CODE_PREFIX : LOGIN_CODE_PREFIX;
            redisUtil.del(prefix + phone);
            log.debug("清除验证码成功: phone={}, type={}", phone, type);
        } catch (Exception e) {
            log.error("清除验证码失败: phone={}, type={}", phone, type, e);
        }
    }
    
    /**
     * 检查发送频率限制
     */
    private boolean isRateLimited(String phone, String type) {
        try {
            String key = SEND_LIMIT_PREFIX + phone + ":" + type;
            return redisUtil.hasKey(key);
        } catch (Exception e) {
            log.error("检查发送频率限制失败: phone={}, type={}", phone, type, e);
            return false;
        }
    }
}
